`timescale 1ns / 1ps
module Forwarding_unit(
    input [31:0] ID_inst,
    input [31:0] EXE_inst,
    input [31:0] MEM_inst,
    input [31:0] WB_inst,
    input        EXE_rs1_use,
    input        EXE_rs2_use,
    input [1:0]  MEM_wb_sel,
    input        MEM_we_reg,
    input        WB_we_reg,
    input [63:0] MEM_alu_res,
    input [63:0] MEM_mem,
    input [63:0] dataW,
    input        MEM_csr_we,
    input [63:0] MEM_csr_val,
    input [63:0] MEM_csr_res,

    output  [63:0] Forward_data1,
    output  [63:0] Forward_data2,
    output         ForwardA,
    output         ForwardB
);


wire [4:0] ID_rs1 = ID_inst[19:15];
wire [4:0] ID_rs2 = ID_inst[24:20];
wire [4:0] ID_rd = ID_inst[11:7];
wire [4:0] EXE_rs1 = EXE_inst[19:15];
wire [4:0] EXE_rs2 = EXE_inst[24:20];
wire [4:0] EXE_rd = EXE_inst[11:7];
wire [4:0] MEM_rd = MEM_inst[11:7];
wire [4:0] WB_rd = WB_inst[11:7];

wire EXMEM_Hazard1 = MEM_we_reg & MEM_rd == EXE_rs1 & EXE_rs1_use & MEM_rd != 0;
wire EXMEM_Hazard2 = MEM_we_reg & MEM_rd == EXE_rs2 & EXE_rs2_use & MEM_rd != 0;
wire EXWB_Hazard1 = WB_we_reg & WB_rd == EXE_rs1 & EXE_rs1_use & WB_rd!=0;
wire EXWB_Hazard2 = WB_we_reg & WB_rd == EXE_rs2 & EXE_rs2_use & WB_rd!=0;

wire [63:0] dataM =  MEM_csr_we ? MEM_csr_val:(MEM_wb_sel == 2'b10 ? MEM_mem: MEM_alu_res);

assign Forward_data1 = EXMEM_Hazard1 ? dataM:(EXWB_Hazard1 ? dataW : 0);
assign Forward_data2 = EXMEM_Hazard2 ? dataM:(EXWB_Hazard2 ? dataW : 0);
assign ForwardA = EXMEM_Hazard1 | EXWB_Hazard1;
assign ForwardB = EXMEM_Hazard2 | EXWB_Hazard2;

endmodule